﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using OpenTK.Audio.OpenAL;
using OpenTK.Audio;

namespace Clandestine.Audio
{
    // 'Source' in OpenAL parlance, naturalement.
	// TODO: Handle streaming stuff!  Ignores it completely right now.
    public class Sound
    {
		public readonly Audio Audio;
		internal readonly StreamingBuffer Buffer;
		internal int sourceId = 0;
		
        public Sound(Audio audio, string filename)
        {
            this.Audio = audio;
			
			this.Audio.LockALAndMakeActive();
			
			sourceId = AL.GenSource();
			
			this.Buffer = (StreamingBuffer) StreamingBuffer.AutoCreateBuffer(audio, filename, sourceId);
			
			// TODO: err check here!!
			
			//AL.Source(sourceId, ALSourcei.Buffer, ((SimpleBuffer)this.Buffer).GetBufferId()); // DON'T do this for streaming!!
			AL.Source(sourceId, ALSourcef.Pitch, 1f); // gotta expose this - could be hysterical
			AL.Source(sourceId, ALSourcef.Gain, 1f);
			AL.Source(sourceId, ALSource3f.Position, 0f, 0f, 0f);
			AL.Source(sourceId, ALSource3f.Velocity, 0f, 0f, 0f);
			AL.Source(sourceId, ALSourceb.Looping, false); // this could be useful for music, streaming shit! <.<
			AL.Source(sourceId, ALSourcef.RolloffFactor, 0f);
			
			this.Audio.UnlockAL();
        }
		
		public bool Playing
		{
			get
			{
				this.Audio.LockALAndMakeActive();
				ALSourceState state = this.state;
				this.Audio.UnlockAL();
				
				return (state == ALSourceState.Playing);
			}
		}
		
		private ALSourceState state
		{
			get
			{
				int state_;
				AL.GetSource(sourceId, ALGetSourcei.SourceState, out state_);
				ALSourceState state = (ALSourceState)state_;
				return state;
			}
		}
		
		public void Play()
		{
			this.Audio.LockALAndMakeActive();
			
			ALSourceState state = this.state;
			
			if (state == ALSourceState.Initial || state == ALSourceState.Stopped)
				Buffer.PlayFromStart();
			else if (state == ALSourceState.Playing)
				return;
			
			AL.SourcePlay(sourceId);
			
			this.Audio.UnlockAL();
		}
		
		public void Stop()
		{
			this.Audio.LockALAndMakeActive();
			
			AL.SourceStop(sourceId);
			
			Buffer.TearDown();
			
			this.Audio.UnlockAL();
		}
		
		public void Pause()
		{
			this.Audio.LockALAndMakeActive();
			
			AL.SourcePause(sourceId);
			
			this.Audio.UnlockAL();
		}
		
		public void Dispose()
		{
			if (sourceId != 0)
			{
				Buffer.Destroy();
				AL.DeleteSource(sourceId);
				sourceId = 0;
			}
		}
    }
}
